//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "IOMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "JvHidControllerClass"
#pragma resource "*.dfm"
TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
  int I;
  AnsiString S;

  // place the SpeedButtons in an array for indexed access
  // mark them with their array index
  for(I = 0; I < 8; I++)
  {
    LEDs[I] = (TSpeedButton *) FindComponent(S.sprintf("LED%d", I));
    LEDs[I]->Tag = I;
  };
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::FormActivate(TObject *Sender)
{
  // the first OnDeviceChange could not access the controls
  // so it is repeated here
  UpdateControls();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::UpdateControls(void)
{
  int I;
  AnsiString S;

  // OnDeviceChange happens before OnCreate so the LEDs are not assigned yet
  if(LEDs[0] != NULL)
  {
    // enable/disable the controls
    for(I = 0; I < 8; I++)
    {
      LEDs[I]->Enabled = (IOWarrior != NULL);
      if(IOWarrior == NULL)
        LEDs[I]->Down = false;
    }
    BlockingRead->Enabled = (IOWarrior != NULL);

    if(IOWarriorDetected != NULL)
      if(IOWarrior != NULL)
        IOWarriorDetected->Caption = "IO-Warrior is plugged in";
      else
        IOWarriorDetected->Caption = "No IO-Warrior is plugged in";
  }
}
//---------------------------------------------------------------------------

bool __stdcall FindIOWarrior(TJvHidDevice *HidDev)
{
  // the IO-Warrior shows up as two devices
  // we want access to the IO-Warrior device for the IO pins
  // the other one with a InputReportByteLength of 8 is for access to
  // the optional LCD module
  return (HidDev->Attributes.VendorID == cCodeMercenariesVID &&
    HidDev->Attributes.ProductID == cIOWarriorPID &&
    HidDev->Caps.InputReportByteLength == 5);
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::HidCtlDeviceChange(TObject *Sender)
{
  int I;
  unsigned int BytesWritten;

  // Free the device object if it has been unplugged
  if(IOWarrior != NULL && !IOWarrior->IsPluggedIn)
    FreeAndNil(&IOWarrior);

  // if no IO-Warrior in use yet then search for one
  if(IOWarrior == NULL)
    if(HidCtl->CheckOutByCallback(IOWarrior, FindIOWarrior))
    {
      // initialize the output report
      IOWarriorOutputReport.ReportID = 0;
      // the IO-Warrior LEDs use negative logic
      for(I = 0; I < 4; I++)
        IOWarriorOutputReport.IOBits[I] = 0xFF;
      // write the bits to the IO-Warrior to reset the LEDs
      IOWarrior->WriteFile(&IOWarriorOutputReport, sizeof(IOWarriorOutputReport), BytesWritten);
    }

  // update the controls on the form
  UpdateControls();
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::LEDClick(TObject *Sender)
{
  int LedIdx;
  unsigned int BytesWritten;

  // use the Tag assigned in FormCreate
  LedIdx = ((TSpeedButton *) Sender)->Tag;

  // translate SpeedButton state into correct bit in IOBits[3]
  // IO-Warrior uses negative logic
  if(LEDs[LedIdx]->Down)
    // set the bit to 0 to switch the LED on
    IOWarriorOutputReport.IOBits[cLEDByte] &= ~(1 << LedIdx);
  else
    // set the bit to 1 to switch the LED off
    IOWarriorOutputReport.IOBits[cLEDByte] |= (1 << LedIdx);

  // write the bits to the IO-Warrior
  IOWarrior->WriteFile(&IOWarriorOutputReport, sizeof(IOWarriorOutputReport), BytesWritten);
}
//---------------------------------------------------------------------------

char *OrdToBinary(unsigned char Value)
{
  int I;
  unsigned char B;
  char *P;
  static char Buffer[9];

  P = Buffer+7;
  B = Value;
  for(I = 0; I < 8; I++)
  {
    *P = '0' + (B & 0x1);
    P--;
    B >>= 1;
  }
  Buffer[8] = '\0';
  return (Buffer);
}

//---------------------------------------------------------------------------
void __fastcall TMainForm::BlockingReadClick(TObject *Sender)
{
  int I;
  unsigned int BytesRead;
  TIOWarriorIOReport IOWarriorInputReport;

  InputBits->Caption = "";
  if(IOWarrior->ReadFile(&IOWarriorInputReport, sizeof(IOWarriorInputReport), BytesRead))
    for(I = 0; I < 4; I++)
      InputBits->Caption = InputBits->Caption + OrdToBinary(IOWarriorInputReport.IOBits[I]);
}
//---------------------------------------------------------------------------

